﻿using System;
using Pretext.Arguments;
using System.IO;
using System.Collections.Generic;
using Pretext.Logging;

namespace Pretext {
    public class PretextManager {

        public event EventHandler<FileEventArgs> FileBeingProcessed;
        public event EventHandler<FileEventArgs> FileSaved;
		public event EventHandler<LogEventArgs> LogItem;

        // switch variables
        public bool Prompt { get; set; }
        public bool IncludeSubfolders { get; set; }
        public bool VerboseMode { get; set; }
        public bool Confirm { get; set; }

        public const string DefaultFileSearchFilter = @"*.pretext";
        public string FileSearchFilter { get; private set; }

        public PretextSession Session { get; private set; }

		public string SourceDirectory { get; private set; }
        public string SourceFile { get; set; }
        bool singleFileOnly = false;

        public PretextManager(PretextSession session) {

            this.Session = session;
            FileSearchFilter = DefaultFileSearchFilter;

			// bind to the log events of the session manager
			this.Session.LogItem += new EventHandler<Pretext.Logging.LogEventArgs>(Session_LogItemAdded);

        }

		void Session_LogItemAdded(object sender, Pretext.Logging.LogEventArgs e) {

			// re-raise the event
			if (LogItem != null)
				LogItem(this, e);

		}

        public void ProcessArguments(string[] args) {

            // parse the arguments
            ArgumentParser argParser = new ArgumentParser(args);

            string source = argParser.Arguments[0];

            if (File.Exists(source)) {

                SourceFile = source;
                SourceDirectory = Path.GetDirectoryName(source);
                Pretexter.WorkingDirectory = SourceDirectory;
                singleFileOnly = true;

            } else if (Directory.Exists(source)) {

                // set the source directory
                SourceDirectory = source;
                singleFileOnly = false;

            } else {
                throw new FileNotFoundException(source + " file could not be found.");
            }

            ProcessSwitches(argParser.Switches);

        }

        public string[] GetPretextFiles(string directory) {
            return Directory.GetFiles(directory, FileSearchFilter);
        }

        public void ProcessSwitches(List<Switch> switches) {

            foreach (Switch s in switches) {

                if (s is VariableSwitch) {

                    VariableSwitch varSwitch = s as VariableSwitch;
                    this.Session.Variables[varSwitch.VariableName] = varSwitch.VariableValue;

                } else {

                    // process normal switches

                    switch (s.SwitchTypeChar) {
                        case 'p':

                            Prompt = true;

                            break;
                        case 's':

                            IncludeSubfolders = true;
                            
                            break;
                        case 'b':

                            
							VerboseMode = true;

                            break;
                    }

                }

            }

        }

        public void Process() {

            // set the options
            Pretexter.VerboseMode = VerboseMode;

            if (singleFileOnly) {

                processFile(SourceFile);

            } else {

                Pretexter.WorkingDirectory = SourceDirectory;
                processDirectory(SourceDirectory, true);
            }

        }

        void processFile(string file) {

            FileProcessor processor = new FileProcessor(file);
            processor.FileSaved += new EventHandler<FileEventArgs>(processor_FileSaved);

            if (FileBeingProcessed != null)
                FileBeingProcessed(this, new FileEventArgs(processor.SourceFile));

            processor.Process();

        }

        private void processDirectory(string directory, bool includeSubfolders) {

			Pretexter.WorkingDirectory = Path.GetFullPath(directory);
			string[] files = GetPretextFiles(directory);

            List<FileProcessor> processors = new List<FileProcessor>(files.Length);

            foreach (string file in files)
                processFile(file);

            if (IncludeSubfolders) {
                // process sub-folders too
                foreach (string folder in Directory.GetDirectories(directory)) {
                    processDirectory(folder, true);
                }
            }

        }

        void processor_FileSaved(object sender, FileEventArgs e) {
            if (FileSaved != null)
                FileSaved(this, e);
        }



    }
}